package com.lagou.edu.io.impl;

import com.lagou.edu.annotation.MiniAutoWired;
import com.lagou.edu.annotation.MiniComponent;
import com.lagou.edu.annotation.MiniRepository;
import com.lagou.edu.annotation.MiniService;
import com.lagou.edu.config.BeanDefinition;
import com.lagou.edu.config.PropertyValue;
import com.lagou.edu.io.ResourceLoader;
import com.lagou.edu.utils.PackageScanUtils;
import com.lagou.edu.utils.ResolveUtils;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;

/**
 * @ClassName: AbstructBeanDefinitionReader
 * @Auther: Jerry
 * @Date: 2020/7/8 16:58
 * @Desctiption: TODO
 * @Version: 1.0
 */
public class DefaultResourceLoader implements ResourceLoader {

    /**
     * 读取配置java文件
     * @param packageScan 包扫描
     * @param excludePackage 排除方案
     * @return {@link List<BeanDefinition>}* @throws ClassNotFoundException 类没有发现异常
     */
    @Override
    public List<BeanDefinition> reader(String packageScan, String excludePackage) throws ClassNotFoundException {
        List<BeanDefinition> beanDefinitions = new ArrayList<>();
        List<String> nameList = PackageScanUtils.doScanner(packageScan, excludePackage);
        for (String name : nameList) {
            // 实例化对象
            Class<?> clazz = Class.forName(name);
            if (clazz.isAnnotationPresent(MiniComponent.class)) {
                MiniComponent component = clazz.getAnnotation(MiniComponent.class);
                // 获取注解的值
                String beanName = component.value();
                if ("".equals(beanName)){
                    beanName = ResolveUtils.lowerFirstCase(clazz.getSimpleName());
                }
                parseBeanDefinition(beanDefinitions, name, clazz, beanName);
                continue;
            } else if (clazz.isAnnotationPresent(MiniRepository.class)) {
                MiniRepository repository = clazz.getAnnotation(MiniRepository.class);
                String beanName = repository.value();
                if ("".equals(beanName)){
                    beanName = ResolveUtils.lowerFirstCase(clazz.getSimpleName());
                }
                parseBeanDefinition(beanDefinitions, name, clazz, beanName);
                continue;
            } else if (clazz.isAnnotationPresent(MiniService.class)) {
                MiniService service = clazz.getAnnotation(MiniService.class);
                String beanName = service.value();
                if ("".equals(beanName)) {
                    beanName = ResolveUtils.lowerFirstCase(clazz.getSimpleName());
                }
                parseBeanDefinition(beanDefinitions, name, clazz, beanName);
                continue;
            }
        }
        return beanDefinitions;
    }

    private void parseBeanDefinition(List<BeanDefinition> beanDefinitions, String className, Class<?> clazz, String beanName) {
        List<PropertyValue> propertyValueList = new ArrayList<>();
        BeanDefinition beanDefinition = new BeanDefinition();
        beanDefinition.setClassName(className);
        beanDefinition.setBeanClass(clazz);
        beanDefinition.setBeanName(beanName);
        Field[] declaredFields = clazz.getDeclaredFields();
        for (Field field : declaredFields) {
            // 获取有autowired注解的字段
            MiniAutoWired autoWired = field.getAnnotation(MiniAutoWired.class);
            if (autoWired != null) {
                PropertyValue propertyValue = new PropertyValue();
                propertyValue.setName(field.getName());
                propertyValue.setRefFlag(true);
                propertyValue.setType(field.getType());
                // 获取自动注入的属性值
                String newBeanName = autoWired.value().trim();
                if ("".equals(newBeanName)) {
                    newBeanName = ResolveUtils.lowerFirstCase(field.getType().getName());
                }
                propertyValue.setBeanName(newBeanName);
                propertyValueList.add(propertyValue);
            } else {
                PropertyValue propertyValue = new PropertyValue();
                propertyValue.setName(field.getName());
                propertyValue.setRefFlag(false);
                propertyValue.setType(field.getType());
                propertyValueList.add(propertyValue);
            }
        }
        beanDefinition.setPropertyValues(propertyValueList);
        beanDefinitions.add(beanDefinition);
    }
}
